package com.alibaba.citrus.ots.application.report.ability.repository.impl;

import com.alibaba.citrus.ots.application.report.ability.repository.BaseDataQueryRepository;
import com.alibaba.citrus.ots.application.report.ability.repository.BaseInventoryImportRepository;
import com.alibaba.citrus.ots.application.report.ability.utils.DomUtil;
import com.alibaba.citrus.ots.common.annotation.FacadeInvoker;
import com.alibaba.citrus.ots.common.util.ThreadPageUtil;
import com.alibaba.cz.base.tool.StringUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.model.dto.OrganizationSDO;
import com.epoch.app.bcorder.model.dto.WarehouseInfo;
import com.epoch.app.crplatformenhance.sdo.CustomerAddressSDO;
import com.epoch.app.crunifiedinventory.model.dto.GetListWarehouseStockRequest;
import com.epoch.app.crunifiedinventory.model.dto.WarehouseInventory;
import com.epoch.app.crunifiedinventory.service.CrUnifiedInventoryService;
import com.epoch.app.otsapplicationreportsdk.contants.OtsApplicationReportSdkConstants;
import com.epoch.app.otsapplicationreportsdk.model.dto.GoodsDO;
import com.epoch.app.otsapplicationreportsdk.model.enums.InventoryTypeEnum;
import com.epoch.app.otsapplicationreportsdk.storeinventorydetail.dto.BatchCreateRequest;
import com.epoch.app.otsapplicationreportsdk.storeinventorydetail.dto.BatchUpdateRequest;
import com.epoch.app.otsapplicationreportsdk.storeinventorydetail.dto.LoadListRequest;
import com.epoch.app.otsapplicationreportsdk.storeinventorydetail.model.StoreInventoryDetail;
import com.epoch.app.otsapplicationreportsdk.storeinventorydetail.service.StoreInventoryDetailService;
import com.epoch.app.otsapplicationreportsdk.storeinventorystats.dto.QueryByStoreIdsReadOnlyRequest;
import com.epoch.app.otsapplicationreportsdk.storeinventorystats.dto.QueryByStoreIdsRequest;
import com.epoch.app.otsapplicationreportsdk.storeinventorystats.model.StoreInventoryStats;
import com.epoch.app.otsapplicationreportsdk.storeinventorystats.service.StoreInventoryStatsService;
import com.epoch.app.crunifiedinventory.model.dto.GetInventoryForAnalysisRequest;
import com.epoch.app.crunifiedinventory.model.dto.GetInventoryTotalForAnalysisRequest;
import com.epoch.app.crunifiedinventory.model.dto.GetInventoryTotalForAnalysisResponse;
import com.epoch.app.crunifiedinventory.model.dto.InventoryForAnalysisResp;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

@Service
public class StoreInventoryImportImpl implements BaseInventoryImportRepository {

    private final Log log = Log.getLogger(StoreInventoryImportImpl.class);

    private static final int PAGE_NO_1 = 1;

    private static final int PAGE_SIZE_500 = 500;

    @Resource
    StoreInventoryDetailService storeInventoryDetailService;

    @Resource
    StoreInventoryStatsService storeInventoryStatsService;

    @Resource
    CrUnifiedInventoryService otsUnifiedInventoryService;

    @Resource
    BaseDataQueryRepository baseDataQueryRepository;

    @Resource(name="inventorySyncTaskExecutorV2")
    ThreadPoolTaskExecutor inventorySyncTaskExecutor;

    //拉取库存原子信息
    @Override
    public List<WarehouseInventory> getInventoryList(List<String> warehouseAreaIds,Integer size){
        StopWatch stopwatch = new StopWatch();
        List<Future<List<WarehouseInventory>>> futureList = Lists.newArrayList();
        stopwatch.start("getTotal");
        GetInventoryTotalForAnalysisRequest request = new GetInventoryTotalForAnalysisRequest();
        request.setType(InventoryTypeEnum.STORE.getType());
        request.setWarehouseAreaIdList(warehouseAreaIds);
        GetInventoryTotalForAnalysisResponse totalResult = otsUnifiedInventoryService.getInventoryTotalForAnalysis(request);
        int totalCnt = totalResult.getResult();
        stopwatch.stop();
        int newsize = (size != null && !size.equals(0)) ? size : PAGE_SIZE_500;
        int totalPage = ThreadPageUtil.calculateTotalPage(totalCnt, newsize);
        for (int pageNo = PAGE_NO_1; pageNo <= totalPage; pageNo++) {
            int finalPageNo = pageNo;
            CompletableFuture<List<WarehouseInventory>> future = CompletableFuture.supplyAsync(() -> {
                List<WarehouseInventory> listResult = null;
                GetInventoryForAnalysisRequest futurerequest = new GetInventoryForAnalysisRequest();
                futurerequest.setType(InventoryTypeEnum.STORE.getType());
                futurerequest.setPage(finalPageNo);
                futurerequest.setSize(newsize);
                futurerequest.setWarehouseAreaIdList(warehouseAreaIds);
                try {
                    Result<List<InventoryForAnalysisResp>> resp = otsUnifiedInventoryService.getInventoryForAnalysis(futurerequest);
                    if (resp.isSuccess() && CollectionUtils.isEmpty(resp.getResult())) {
                        return Lists.newArrayList();
                    }
                    listResult = formatQuantity(resp.getResult());
                } catch (Exception e) {
                    log.error("warehouseInventoryImportImpl_pull_getListWarehouseStock_error={}", e.getMessage());
                }
                return listResult;
            }, inventorySyncTaskExecutor);
            futureList.add(future);
        }
        List<WarehouseInventory> result = new ArrayList<>();
        int futureTimes = 1;
        try {
            stopwatch.start("listwarehouseinventory");
            for (Future<List<WarehouseInventory>> future : futureList) {
                List<WarehouseInventory> inventorySubList = future.get();
                result.addAll(inventorySubList);
                futureTimes++;
            }
            stopwatch.stop();
        } catch (Exception e) {
            log.error("warehouseInventoryImportImpl_pull_getListWarehouseStock_wait_occur_error={}", e.getMessage());
        }
        log.info("warehouseInventoryImportImpl_use_time={}s,foreachtimes={}s,inventorySubList_size={}",
                stopwatch.getTotalTimeSeconds(), futureTimes, result.size());
        return result;
    }
    @Override
    public List<WarehouseInventory> getInventoryList() {
        StopWatch stopWatch = new StopWatch("getInventoryList");
        stopWatch.start("getInventoryTotal");
        int totalCnt = getInventoryTotal(InventoryTypeEnum.STORE);
        log.info("storeInventoryImportImpl_getInventoryTotal={}", totalCnt);
        stopWatch.stop();

        int totalPage = totalCnt / PAGE_SIZE_500;
        if (totalCnt % PAGE_SIZE_500 > 0) {
            totalPage++;
        }
        List<Future<List<WarehouseInventory>>> futureList = Lists.newArrayList();
        for (int pageNo = PAGE_NO_1; pageNo <= totalPage; pageNo++) {
            int finalPageNo = pageNo;
            CompletableFuture<List<WarehouseInventory>> future = CompletableFuture.supplyAsync(() -> {
                Result<List<WarehouseInventory>> listResult = null;
                GetListWarehouseStockRequest request = new GetListWarehouseStockRequest();
                request.setType(String.valueOf(InventoryTypeEnum.STORE.getType()));
                request.setPage(finalPageNo);
                request.setSize(PAGE_SIZE_500);
                StopWatch stopWatchNested = new StopWatch("getListWarehouseStock");
                try {
                    stopWatchNested.start("getListWarehouseStock_"+finalPageNo);
                    listResult = otsUnifiedInventoryService.getListWarehouseStock(request);
                    if (listResult == null || CollectionUtils.isEmpty(listResult.getResult())) {
                        return Lists.newArrayList();
                    }
                } catch (Exception e) {
                    log.error("storeInventoryImportImpl_pull_getListWarehouseStock_error={}", e.getMessage());
                } finally {
                    stopWatchNested.stop();
                    log.info("storeInventoryImportImpl_getInventoryList_stopWatchNested_getTotalTimeMillis={}",stopWatchNested.getTotalTimeMillis());
                }
                List<WarehouseInventory> inventorySubList = listResult.getResult();
                return inventorySubList;
            }, inventorySyncTaskExecutor);
            futureList.add(future);
        }
        List<WarehouseInventory> result = new ArrayList<>();
        try {
            for (Future<List<WarehouseInventory>> future : futureList) {
                List<WarehouseInventory> inventorySubList = future.get();
                result.addAll(inventorySubList);
            }
        } catch (Exception e) {
            log.error("storeInventoryImportImpl_pull_getListWarehouseStock_wait_occur_error={}", e.getMessage());
        }
        log.info("storeInventoryImportImpl_getInventoryList_stopWatch_getTotalTimeMillis={}", stopWatch.getTotalTimeMillis());
        return result;
    }

    //统计数据入库
    @Override
    public void doImportData(List<WarehouseInventory> importInventoryList, List<String> importWarehouseAreaIds, Map<String, GoodsDO> goodsDOMap, boolean firstSyncOfToday){
        StopWatch stopWatch = new StopWatch("storeInventoryImport");
        stopWatch.start("doImportData");
        // 根据仓库地址分组
        Map<String, List<WarehouseInventory>> mapOrg = importInventoryList.stream().collect(Collectors.groupingBy(x -> x.getWarehouseAreaId()));
        List<String> warehouseAreaIds = mapOrg.entrySet().stream().map(x -> x.getKey()).collect(Collectors.toList());
        // 获取门店归属分子公司、业务渠道
        Map<String, String> storeSalesOrgMap = this.getStoreSalesOrgInfo(warehouseAreaIds);
        List<Future<List<StoreInventoryStats>>> futureList = Lists.newArrayList();
        for (Map.Entry<String, List<WarehouseInventory>> entryOrg : mapOrg.entrySet()) {
            CompletableFuture<List<StoreInventoryStats>> future = CompletableFuture.supplyAsync(() -> {
                String storeId = entryOrg.getKey();
                // 根据货品ID分组
                Map<String, List<WarehouseInventory>> mapItem = entryOrg.getValue().stream().collect(Collectors.groupingBy(x -> x.getGoodsId()));
                String bizUnitIdAndChannelCode = storeSalesOrgMap.get(storeId);
                String bizUnitId = null;
                String channelCode = null;
                if(StringUtils.isNotBlank(bizUnitIdAndChannelCode)){
                    String[] splitArray = bizUnitIdAndChannelCode.split("#");
                    bizUnitId = splitArray[0];
                    channelCode = splitArray[1];
                }
                if (StringUtils.isBlank(bizUnitId) || "-1".equals(bizUnitId)) {
                    log.info("storeInventoryImportImpl_store_bizUnitId_is_null, warehouseAreaId={}", storeId);
                }
                if (StringUtils.isBlank(channelCode) || "-1".equals(channelCode)) {
                    log.info("storeInventoryImportImpl_store_channelCode_is_null, warehouseAreaId={}", storeId);
                }

                List<StoreInventoryDetail> detailList = new ArrayList<>();
                for (Map.Entry<String, List<WarehouseInventory>> entryItem : mapItem.entrySet()) {
                    StoreInventoryDetail detail = buildInventoryDetail(entryItem, goodsDOMap);
                    if (detail != null) {
                        detail.setBizUnitId(bizUnitId);
                        detail.setChannelCode(channelCode);
                        detailList.add(detail);
                    }
                }

                List<StoreInventoryStats> statsList = new ArrayList<>();
                if (CollectionUtils.isNotEmpty(detailList)) {
                    // 保存网点货品库存统计
                    saveInventoryDetail(storeId, detailList, firstSyncOfToday);
                    StoreInventoryStats stats = collectInventoryStats(detailList);
                    statsList.add(stats);
                }
                return statsList;
            }, inventorySyncTaskExecutor);
            futureList.add(future);
        }
        List<StoreInventoryStats> statsList = new ArrayList<>();
        try {
            for (Future<List<StoreInventoryStats>> future : futureList) {
                List<StoreInventoryStats> futureStats = future.get();
                statsList.addAll(futureStats);
            }
        } catch (Exception e) {
            log.error("storeInventoryImportImpl_doImportData_get_futureList_occor_error", e);
        }

        // 保存网点库存统计
        if (CollectionUtils.isNotEmpty(statsList)) {
            saveInventoryStats(statsList, firstSyncOfToday);
        }
        log.info("storeInventoryImportImpl_savestats,size={}",statsList.size());

        //报表数据没做对比的，报表库存全部置为0
        if(!firstSyncOfToday){
            String statisticalDate = DomUtil.getToday();
            List<String> notCompareStoreIds = importWarehouseAreaIds.stream().filter(x->!warehouseAreaIds.contains(x)).collect(Collectors.toList());
            if(CollectionUtils.isEmpty(notCompareStoreIds)){
                return;
            }
            QueryByStoreIdsRequest queryRequest = new QueryByStoreIdsRequest();
            queryRequest.setStatisticalDate(DomUtil.getToday());
            queryRequest.setStoreIds(notCompareStoreIds);
            Result<List<StoreInventoryStats>> reportQueryResult = storeInventoryStatsService.queryByStoreIds(queryRequest);
            if(Objects.nonNull(reportQueryResult) && CollectionUtils.isNotEmpty(reportQueryResult.getResult())){
                List<String> updateStoreIds = reportQueryResult.getResult().stream()
                        .filter(x->!isZeroInventoryQuantity(null,x))
                        .map(x->x.getStoreId()).collect(Collectors.toList());

                if(CollectionUtils.isNotEmpty(updateStoreIds)){
                    log.info("storeInventoryImportImpl_notCompareStoreIds={}", JSONObject.toJSONString(updateStoreIds));
                    StoreInventoryDetail detailUpdate = new StoreInventoryDetail();
                    StoreInventoryStats statsUpdate = new StoreInventoryStats();
                    initZeroInventoryQuantity(detailUpdate,statsUpdate);
                    BatchUpdateRequest batchUpdateDetailRequest = new BatchUpdateRequest();
                    BeanUtils.copyProperties(detailUpdate,batchUpdateDetailRequest);
                    batchUpdateDetailRequest.setStatisticalDate(statisticalDate);
                    batchUpdateDetailRequest.setStoreIds(updateStoreIds);
                    storeInventoryDetailService.batchUpdate(batchUpdateDetailRequest);
                    com.epoch.app.otsapplicationreportsdk.storeinventorystats.dto.BatchUpdateRequest  batchUpdateStatsRequest = new com.epoch.app.otsapplicationreportsdk.storeinventorystats.dto.BatchUpdateRequest();
                    BeanUtils.copyProperties(statsUpdate,batchUpdateStatsRequest);
                    batchUpdateStatsRequest.setStatisticalDate(statisticalDate);
                    batchUpdateStatsRequest.setStoreIds(updateStoreIds);
                    storeInventoryStatsService.batchUpdate(batchUpdateStatsRequest);
                }
            }
        }
        stopWatch.stop();
        log.info("storeInventoryImportImpl_doImportData_stopWatch_getTotalTimeMillis={}", stopWatch.getTotalTimeMillis());
    }

    //获取门店归属分子公司、业务渠道
    @FacadeInvoker
    private Map<String,String> getStoreSalesOrgInfo(List<String> warehouseAreaIds){
        Map<String,WarehouseInfo> storeMap = baseDataQueryRepository.getStoreInfo(warehouseAreaIds);
        List<String> saleOrgIds = storeMap.entrySet().stream().map(x->x.getValue().getSaleOrgId()).collect(Collectors.toList());
        Map<String, OrganizationSDO> saleOrgMap = baseDataQueryRepository.batchQueryOrganization(saleOrgIds);
        List<String> addressIds = storeMap.entrySet().stream().map(x->x.getValue().getAddressCode()).collect(Collectors.toList());
        Map<String, CustomerAddressSDO> addressMap = baseDataQueryRepository.batchQueryCustomerAddress(addressIds);
        Map<String,String> storeSalesOrgMap = new HashMap<>();//门店id,分子公司id_业务渠道code
        for (Map.Entry<String, WarehouseInfo> entry: storeMap.entrySet()){
            String storeId = entry.getKey();
            String orgId = entry.getValue().getSaleOrgId();
            String bizUnitId = StringUtil.isNotEmpty(orgId) && saleOrgMap.get(orgId)!=null?saleOrgMap.get(orgId).getParentId():"-1";
            String addressId = entry.getValue().getAddressCode();
            String channelCode = StringUtil.isNotEmpty(addressId) && addressMap.get(addressId)!=null?addressMap.get(addressId).getChannelCode():"-1";
            storeSalesOrgMap.put(storeId, bizUnitId+"#"+channelCode);
        }
        return storeSalesOrgMap;
    }

    //构建detail
    private StoreInventoryDetail buildInventoryDetail(Map.Entry<String, List<WarehouseInventory>> entry, Map<String, GoodsDO> goodsDOMap) {
        GoodsDO goodsDO = goodsDOMap.get(entry.getKey());
        if (goodsDO == null) {
            log.info("goods_exist_storeInventory_but_scItem_id_error={}", entry.getKey());
            return null;
        }
        List<WarehouseInventory> itemInventoryList = entry.getValue();
        return collectInventoryDetail(goodsDO, itemInventoryList);
    }

    private void saveInventoryDetail(String storeId, List<StoreInventoryDetail> todoList, boolean firstSyncOfToday) {
        //当体首次同步则直接插入
        if (firstSyncOfToday) {
            BatchCreateRequest batchCreateRequest = new BatchCreateRequest();
            batchCreateRequest.setReportList(todoList);
            Object result = storeInventoryDetailService.batchCreate(batchCreateRequest);
        } else {
            //根据目前纪元单次最多只能查出1000条的数据限制，若未来单仓出现全链路明细超过1000条，会存在重复数据风险
            LoadListRequest request= new LoadListRequest();
            request.setStart(0);
            request.setLimit(2000);
            request.setStoreId(storeId);
            request.setStatisticalDate(DomUtil.getToday());
            Result<List<StoreInventoryDetail>> response;
            if("1".equals(OtsApplicationReportSdkConstants.QUERY_READONLY_DATABASE())){
                com.epoch.app.otsapplicationreportsdk.storeinventorydetail.dto.LoadListReadOnlyRequest readOnlyRequest=new com.epoch.app.otsapplicationreportsdk.storeinventorydetail.dto.LoadListReadOnlyRequest();
                BeanUtils.copyProperties(request, readOnlyRequest);
                response = storeInventoryDetailService.loadListReadOnly(readOnlyRequest);
            }else {
                response = storeInventoryDetailService.loadList(request);
            }
            List<StoreInventoryDetail> existedList = new ArrayList<>();
            if(Objects.nonNull(response) && CollectionUtils.isNotEmpty(response.getResult())){
                existedList = response.getResult();
            }
            for (StoreInventoryDetail todo : todoList) {
                StoreInventoryDetail existed = existedOfList(todo, existedList);
                if (existed != null) {
                    if (!needUpdate(todo, existed)) {
                        existed.setUpdater("1");
                        log.info("StoreInventoryDetail_exist_and_nochanged,id={}", existed.getId());
                        continue;
                    }
                    BeanUtils.copyProperties(todo, existed, "id");
                    existed.setGmt_modified(new Date());
                    Object updateResponse = storeInventoryDetailService.update(existed);
                    existed.setUpdater("1");
                } else {
                    Object createResponse = storeInventoryDetailService.create(todo);
                }
            }

            //报表数据没做对比的，报表库存全部置为0
            List<StoreInventoryDetail> notCompareDetailList = existedList.stream()
                    .filter(x->!"1".equals(x.getUpdater()))
                    .filter(x->!isZeroInventoryQuantity(x,null))//过滤库存已经是0的不做数据库变更
                    .collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(notCompareDetailList)){
                List<Long> ids = notCompareDetailList.stream().map(x->x.getId()).collect(Collectors.toList());
                log.info("StoreInventoryDetail_exist_and_notCompareDetail,storeId={},list={}", storeId,JSONObject.toJSONString(ids));
                for (StoreInventoryDetail detail : notCompareDetailList) {
                    initZeroInventoryQuantity(detail,null);
                    Object updateResponse = storeInventoryDetailService.update(detail);
                }
            }
        }
    }
    @Override
    public boolean firstSyncOfToday(){
        com.epoch.app.otsapplicationreportsdk.storeinventorystats.dto.LoadListRequest request = new com.epoch.app.otsapplicationreportsdk.storeinventorystats.dto.LoadListRequest();
        request.setStatisticalDate(DomUtil.getToday());
        return CollectionUtils.isEmpty(storeInventoryStatsService.loadList(request).getResult());
    }

    private List<StoreInventoryDetail> queryStoreInventoryDetailList(String storeId,String statisticalDate,int start,int limit){
        LoadListRequest request= new LoadListRequest();
        request.setStart(start);
        request.setLimit(limit);
        request.setStoreId(storeId);
        request.setStatisticalDate(statisticalDate);
        Result<List<StoreInventoryDetail>> response;
        if("1".equals(OtsApplicationReportSdkConstants.QUERY_READONLY_DATABASE())){
            com.epoch.app.otsapplicationreportsdk.storeinventorydetail.dto.LoadListReadOnlyRequest readOnlyRequest=new com.epoch.app.otsapplicationreportsdk.storeinventorydetail.dto.LoadListReadOnlyRequest();
            BeanUtils.copyProperties(request, readOnlyRequest);
            response = storeInventoryDetailService.loadListReadOnly(readOnlyRequest);
        }else {
            response = storeInventoryDetailService.loadList(request);
        }
        List<StoreInventoryDetail> list = new ArrayList<>();
        if(Objects.nonNull(response) && CollectionUtils.isNotEmpty(response.getResult())){
            list = response.getResult();
        }
        return list;
    }

    private boolean needUpdate(StoreInventoryDetail todo, StoreInventoryDetail existed){
        return !todo.getTotalQuantity().equals(existed.getTotalQuantity()) ||
                !todo.getAvailableQuantity().equals(existed.getAvailableQuantity()) ||
                !todo.getWithholdingQuantity().equals(existed.getWithholdingQuantity()) ||
                !todo.getOnwayQuantity().equals(existed.getOnwayQuantity()) ||
                !todo.getThisMonthQuantity().equals(existed.getThisMonthQuantity()) ||
                !todo.getOneMonthQuantity().equals(existed.getOneMonthQuantity()) ||
                !todo.getTwoMonthsQuantity().equals(existed.getTwoMonthsQuantity()) ||
                !todo.getThreeMonthsQuantity().equals(existed.getThreeMonthsQuantity()) ||
                !todo.getFourMonthsQuantity().equals(existed.getFourMonthsQuantity()) ;
    }

    private boolean needModify(StoreInventoryStats todo, StoreInventoryStats existed){
        return !todo.getTotalQuantity().equals(existed.getTotalQuantity()) ||
                !todo.getAvailableQuantity().equals(existed.getAvailableQuantity()) ||
                !todo.getWithholdingQuantity().equals(existed.getWithholdingQuantity()) ||
                !todo.getOnwayQuantity().equals(existed.getOnwayQuantity()) ||
                !todo.getThisMonthQuantity().equals(existed.getThisMonthQuantity()) ||
                !todo.getOneMonthQuantity().equals(existed.getOneMonthQuantity()) ||
                !todo.getTwoMonthsQuantity().equals(existed.getTwoMonthsQuantity()) ||
                !todo.getThreeMonthsQuantity().equals(existed.getThreeMonthsQuantity()) ||
                !todo.getFourMonthsQuantity().equals(existed.getFourMonthsQuantity()) ;
    }

    private void saveInventoryStats(List<StoreInventoryStats> todoList, boolean firstSyncOfToday){
        //当体首次同步则直接插入
        if (firstSyncOfToday){
            com.epoch.app.otsapplicationreportsdk.storeinventorystats.dto.BatchCreateRequest batchCreateRequest = new com.epoch.app.otsapplicationreportsdk.storeinventorystats.dto.BatchCreateRequest();
            batchCreateRequest.setReportList(todoList);
            Object response = storeInventoryStatsService.batchCreate(batchCreateRequest);
        }else {
            //分析条数超过2000会有问题,改为1条条查对比
            for (StoreInventoryStats todo:todoList){
                QueryByStoreIdsRequest request = new QueryByStoreIdsRequest();
                request.setStoreIds(Arrays.asList(todo.getStoreId()));
                request.setStatisticalDate(DomUtil.getToday());
                Result<List<StoreInventoryStats>> response;
                if ("1".equals(OtsApplicationReportSdkConstants.QUERY_READONLY_DATABASE())) {
                    QueryByStoreIdsReadOnlyRequest readOnlyRequest = new QueryByStoreIdsReadOnlyRequest();
                    BeanUtils.copyProperties(request, readOnlyRequest);
                    response = storeInventoryStatsService.queryByStoreIdsReadOnly(readOnlyRequest);
                } else {
                    response = storeInventoryStatsService.queryByStoreIds(request);
                }
                List<StoreInventoryStats> existedList = new ArrayList<>();
                if(Objects.nonNull(response) && CollectionUtils.isNotEmpty(response.getResult())){
                    existedList = response.getResult();
                }
                StoreInventoryStats existed = existedOfList(todo, existedList);
                //已存在的数据则更新
                if (existed!=null){
                    if (!needModify(todo, existed)){
                        log.info("StoreInventoryStats_exist_and_nochanged,id={}", existed.getId());
                        continue;
                    }
                    BeanUtils.copyProperties(todo, existed, "id");
                    existed.setGmt_modified(new Date());
                    Object updateResponse = storeInventoryStatsService.update(existed);
                }else {
                    Object createResponse = storeInventoryStatsService.create(todo);
                }
            }
        }
    }

    //判断是否当前待处理记录是否已存在
    private StoreInventoryDetail existedOfList(StoreInventoryDetail todo, List<StoreInventoryDetail> existedList){
        if (CollectionUtils.isEmpty(existedList)){
            return null;
        }
        for (StoreInventoryDetail existed:existedList){
            if (existed.getGoodsId().equals(todo.getGoodsId())){
                return existed;
            }
        }
        return null;
    }

    //判断是否当前待处理记录是否已存在
    private StoreInventoryStats existedOfList(StoreInventoryStats todo, List<StoreInventoryStats> existedList){
        if (CollectionUtils.isEmpty(existedList)){
            return null;
        }
        for (StoreInventoryStats existed:existedList){
            if (existed.getStoreId().equals(todo.getStoreId())){
                return existed;
            }
        }
        return null;
    }

    //保存明细表
    private StoreInventoryDetail collectInventoryDetail(GoodsDO goodsDO, List<WarehouseInventory> inventoryList){
        StoreInventoryDetail detail = new StoreInventoryDetail();
        detail.setStoreId(inventoryList.get(0).getWarehouseAreaId());
        detail.setStoreName(inventoryList.get(0).getWarehouseName());
        detail.setGoodsId(goodsDO.getGoodsId());
        detail.setGoodsName(goodsDO.getGoodsName());
        detail.setCategoryId(goodsDO.getCategoryId());
        detail.setCategoryName(goodsDO.getCategoryName());
        detail.setStatisticalDate(DomUtil.getToday());
        Integer guaranteePeriod = goodsDO.getGuaranteePeriod();
        //替换为单位关系转换后的 基本单位库存值
        detail.setTotalQuantity(inventoryList.stream().filter(x->x.getUnitConvertedQuantity() != null).mapToLong(WarehouseInventory::getUnitConvertedQuantity).sum());
        detail.setAvailableQuantity(inventoryList.stream().filter(x-> x.getUnitConvertedQuantity() != null).mapToLong(WarehouseInventory::getUnitConvertedQuantity).sum());
        detail.setWithholdingQuantity(inventoryList.stream().mapToLong(WarehouseInventory::getWithholdingQuantity).sum());
        detail.setOnwayQuantity(inventoryList.stream().mapToLong(WarehouseInventory::getOnwayQuantity).sum());
        detail.setFourthExpiredQuantity(inventoryList.stream().filter(x->DomUtil.exceedFourthExpired(x.getDom(),guaranteePeriod)).filter(x->x.getUnitConvertedQuantity() != null).mapToLong(WarehouseInventory::getUnitConvertedQuantity).sum());
        detail.setThirdExpiredQuantity(inventoryList.stream().filter(x->DomUtil.exceedThirdExpired(x.getDom(),guaranteePeriod)).filter(x->x.getUnitConvertedQuantity() != null).mapToLong(WarehouseInventory::getUnitConvertedQuantity).sum());
        detail.setApproachExpiredQuantity(inventoryList.stream().filter(x->DomUtil.approachExpired(x.getDom(),guaranteePeriod)).filter(x->x.getUnitConvertedQuantity() != null).mapToLong(WarehouseInventory::getUnitConvertedQuantity).sum());
        detail.setNormalQuantity(inventoryList.stream().filter(x->DomUtil.lessFourthExpired(x.getDom(),guaranteePeriod)).filter(x->x.getUnitConvertedQuantity() != null).mapToLong(WarehouseInventory::getUnitConvertedQuantity).sum());
        detail.setThisMonthQuantity(inventoryList.stream().filter(x->DomUtil.thisMonth(x.getDom())).filter(x->x.getUnitConvertedQuantity() != null).mapToLong(WarehouseInventory::getUnitConvertedQuantity).sum());
        detail.setOneMonthQuantity(inventoryList.stream().filter(x->DomUtil.oneMonth(x.getDom())).filter(x->x.getUnitConvertedQuantity() != null).mapToLong(WarehouseInventory::getUnitConvertedQuantity).sum());
        detail.setTwoMonthsQuantity(inventoryList.stream().filter(x->DomUtil.twoMonths(x.getDom())).filter(x->x.getUnitConvertedQuantity() != null).mapToLong(WarehouseInventory::getUnitConvertedQuantity).sum());
        detail.setThreeMonthsQuantity(inventoryList.stream().filter(x->DomUtil.threeMonths(x.getDom())).filter(x-> x.getUnitConvertedQuantity() != null).mapToLong(WarehouseInventory::getUnitConvertedQuantity).sum());
        detail.setFourMonthsQuantity(inventoryList.stream().filter(x->DomUtil.fourMonthsAgo(x.getDom())).filter(x->x.getUnitConvertedQuantity() != null).mapToLong(WarehouseInventory::getUnitConvertedQuantity).sum());
        return detail;
    }

    private StoreInventoryStats collectInventoryStats(List<StoreInventoryDetail> detailList){
        StoreInventoryStats stats = new StoreInventoryStats();
        stats.setBizUnitId(detailList.get(0).getBizUnitId());
        stats.setStoreId(detailList.get(0).getStoreId());
        stats.setStoreName(detailList.get(0).getStoreName());
        stats.setChannelCode(detailList.get(0).getChannelCode());
        stats.setStatisticalDate(DomUtil.getToday());
        stats.setTotalQuantity(detailList.stream().mapToLong(StoreInventoryDetail::getTotalQuantity).sum());
        stats.setAvailableQuantity(detailList.stream().mapToLong(StoreInventoryDetail::getAvailableQuantity).sum());
        stats.setWithholdingQuantity(detailList.stream().mapToLong(StoreInventoryDetail::getWithholdingQuantity).sum());
        stats.setOnwayQuantity(detailList.stream().mapToLong(StoreInventoryDetail::getOnwayQuantity).sum());
        stats.setFourthExpiredQuantity(detailList.stream().mapToLong(StoreInventoryDetail::getFourthExpiredQuantity).sum());
        stats.setThirdExpiredQuantity(detailList.stream().mapToLong(StoreInventoryDetail::getThirdExpiredQuantity).sum());
        stats.setApproachExpiredQuantity(detailList.stream().mapToLong(StoreInventoryDetail::getApproachExpiredQuantity).sum());
        stats.setNormalQuantity(detailList.stream().mapToLong(StoreInventoryDetail::getNormalQuantity).sum());
        stats.setThisMonthQuantity(detailList.stream().mapToLong(StoreInventoryDetail::getThisMonthQuantity).sum());
        stats.setOneMonthQuantity(detailList.stream().mapToLong(StoreInventoryDetail::getOneMonthQuantity).sum());
        stats.setTwoMonthsQuantity(detailList.stream().mapToLong(StoreInventoryDetail::getTwoMonthsQuantity).sum());
        stats.setThreeMonthsQuantity(detailList.stream().mapToLong(StoreInventoryDetail::getThreeMonthsQuantity).sum());
        stats.setFourMonthsQuantity(detailList.stream().mapToLong(StoreInventoryDetail::getFourMonthsQuantity).sum());
        return stats;
    }
    private void initZeroInventoryQuantity(StoreInventoryDetail detail,StoreInventoryStats stats) {
        if(Objects.nonNull(detail)){
            detail.setTotalQuantity(0L);
            detail.setAvailableQuantity(0L);
            detail.setWithholdingQuantity(0L);
            detail.setOnwayQuantity(0L);
            detail.setFourthExpiredQuantity(0L);
            detail.setThirdExpiredQuantity(0L);
            detail.setApproachExpiredQuantity(0L);
            detail.setNormalQuantity(0L);
            detail.setThisMonthQuantity(0L);
            detail.setOneMonthQuantity(0L);
            detail.setTwoMonthsQuantity(0L);
            detail.setThreeMonthsQuantity(0L);
            detail.setFourMonthsQuantity(0L);
            detail.setGmt_modified(new Date());
        }
        if(Objects.nonNull(stats)){
            stats.setTotalQuantity(0L);
            stats.setAvailableQuantity(0L);
            stats.setWithholdingQuantity(0L);
            stats.setOnwayQuantity(0L);
            stats.setFourthExpiredQuantity(0L);
            stats.setThirdExpiredQuantity(0L);
            stats.setApproachExpiredQuantity(0L);
            stats.setNormalQuantity(0L);
            stats.setThisMonthQuantity(0L);
            stats.setOneMonthQuantity(0L);
            stats.setTwoMonthsQuantity(0L);
            stats.setThreeMonthsQuantity(0L);
            stats.setFourMonthsQuantity(0L);
            stats.setGmt_modified(new Date());
        }
    }

    private Boolean isZeroInventoryQuantity(StoreInventoryDetail detail,StoreInventoryStats stats) {
        if(Objects.nonNull(detail)){
            return detail.getTotalQuantity().equals(0L)
                    && detail.getAvailableQuantity().equals(0L)
                    && detail.getWithholdingQuantity().equals(0L)
                    && detail.getOnwayQuantity().equals(0L)
                    && detail.getFourthExpiredQuantity().equals(0L)
                    && detail.getThirdExpiredQuantity().equals(0L)
                    && detail.getApproachExpiredQuantity().equals(0L)
                    && detail.getNormalQuantity().equals(0L)
                    && detail.getThisMonthQuantity().equals(0L)
                    && detail.getOneMonthQuantity().equals(0L)
                    && detail.getTwoMonthsQuantity().equals(0L)
                    && detail.getThreeMonthsQuantity().equals(0L)
                    && detail.getFourMonthsQuantity().equals(0L);
        }
        if(Objects.nonNull(stats)){
            return stats.getTotalQuantity().equals(0L)
                    && stats.getAvailableQuantity().equals(0L)
                    && stats.getWithholdingQuantity().equals(0L)
                    && stats.getOnwayQuantity().equals(0L)
                    && stats.getFourthExpiredQuantity().equals(0L)
                    && stats.getThirdExpiredQuantity().equals(0L)
                    && stats.getApproachExpiredQuantity().equals(0L)
                    && stats.getNormalQuantity().equals(0L)
                    && stats.getThisMonthQuantity().equals(0L)
                    && stats.getOneMonthQuantity().equals(0L)
                    && stats.getTwoMonthsQuantity().equals(0L)
                    && stats.getThreeMonthsQuantity().equals(0L)
                    && stats.getFourMonthsQuantity().equals(0L);
        }
        return false;
    }
    //取库存记录总数
    private int getInventoryTotal(InventoryTypeEnum typeEnum){
        GetListWarehouseStockRequest request = new GetListWarehouseStockRequest();
        request.setPage(PAGE_NO_1);
        request.setSize(PAGE_SIZE_500);
        request.setType(String.valueOf(typeEnum.getType()));
        return otsUnifiedInventoryService.getListWarehouseStock(request).getTotal();
    }
    private List<WarehouseInventory> formatQuantity(List<InventoryForAnalysisResp> beforFormatList) {
        List<WarehouseInventory> result = new ArrayList<>();
        for (InventoryForAnalysisResp x : beforFormatList) {
            WarehouseInventory y = new WarehouseInventory();
            y.setWarehouseAreaId(x.getWarehouseAreaId());
            y.setDom(x.getDom());
            y.setTotalQuantity(x.getTotalQuantity());
            y.setInspectQuantity(x.getInspectQuantity());
            y.setWithholdingQuantity(x.getWithholdingQuantity());
            y.setOnwayQuantity(x.getOnwayQuantity());
            y.setFrozenQuantity(x.getFrozenQuantity());
            y.setAvailableQuantity(x.getAvailableQuantity());
            y.setGoodsId(x.getGoodsId());
            //单位转换关系
            y.setUnitConvert(x.getUnitConvert());
            y.setUnitConvertedQuantity(x.getUnitConvertedQuantity());
            result.add(y);
        }
        return result;
    }
    @Override
    public void reAnalysisReport(String statisDate) {

    }
}
